// 《围棋》作者版权所有。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 此文件实现多精度浮点数。
// 类似于GNU MPFR库(https:
// 可以是混合精度。与MPFR不同，舍入模式为
// 不是在每个操作中指定，而是在每个操作数中指定。结果操作数的舍入模式决定操作的舍入模式。这是一个从头开始的实现。

package big

import (
	"fmt"
	"math"
	"math/bits"
)

const debugFloat = false // 启用调试

// 非零有限浮点表示多精度浮点数
// 
// 符号×尾数×2**指数
// 
// 尾数为0.5<=1.0，MinExp<=指数≤MaxExp。
// 浮点也可以是零（+0，-0）或无限（+Inf，-Inf）。
// 所有浮点都是有序的，两个浮点x和y的顺序
// 由x.Cmp（y）定义。
// 
// 每个浮点值还具有精度、舍入模式和精度。
// 精度是
// 可用尾数位数的最大值，表示该值。舍入模式指定如何将结果
// 舍入到尾数位，精度描述了与精确结果相关的
// 舍入错误。
// 
// 除非另有规定，否则
// 为结果指定*浮点变量的所有操作（包括设置器）（通常通过接收器
// 除MANTEP外），根据
// 将数值结果四舍五入到结果变量的精度和四舍五入模式。
// 
// 如果提供的结果精度为0（见下文），则在进行任何
// 精度，舍入模式保持不变。因此，作为结果参数提供的未初始化浮点将其精度设置为由操作数确定的合理值，并且其模式为舍入模式（ToNearestEven）的零值。
// 舍入之前，将其设置为具有最大精度值的参数的
// 
// 通过将所需精度设置为24或53，并使用匹配的舍入
// 模式（通常为ToNearestEven），浮点运算产生的结果
// 与对应于正常值的操作数
// 的相应浮点32或浮点64 IEEE-754算法相同（即，不是非规范的）float32或float64数字。与IEEE-754相比，指数下溢和上溢导致不同的值为0或无穷大，因为浮点指数的范围大得多。指数下溢和上溢导致零（未初始化）浮点数的值已准备好使用，表示
// 精确的数字+0.0，精度为0，四舍五入模式为TEVEN。
// 
// 操作始终采用指针参数（*Float）而是
// 而不是浮点值，每个唯一的浮点值都需要
// 它自己唯一的*浮点指针。要“复制”浮点值，
// 一个现有的（或新分配的）必须使用Float.set方法将Float设置为
// 一个新值；不支持浮点数的浅拷贝
// 并且可能会导致错误。
type Float struct {
	prec uint32
	mode RoundingMode
	acc  Accuracy
	form form
	neg  bool
	mant nat
	exp  int32
}

// 根据IEEE-754规则，浮点操作会导致
// 一个NaN。ErrNaN实现错误接口。
type ErrNaN struct {
	msg string
}

func (err ErrNaN) Error() string {
	return err.msg
}

// NewFloat分配并返回一个新的浮点集合到x，
// 精度为53，取整模式为TENEARESTEven。
// 如果x是NaN，NewFloat将与ErrNaN产生冲突。
func NewFloat(x float64) *Float {
	if math.IsNaN(x) {
		panic(ErrNaN{"NewFloat(NaN)"})
	}
	return new(Float).SetFloat64(x)
}

// 指数和精度限制。
const (
	MaxExp  = math.MaxInt32  // 支持的最大指数
	MinExp  = math.MinInt32  // 支持的最小指数
	MaxPrec = math.MaxUint32 // 支持的最大（理论上）精度；可能内存有限的
)

// 内部表示：非零有限
// 浮点x存储在nat片中，其长度足以容纳x.prec位；
// 该片可以（但不必）如果尾数包含
// 尾随0位，则长度将更短。如果x.mant的msb==1（即
// 将msb完全“左移”），则x.mant将被规范化。因此，如果尾数包含
// 尾随0位或x.prec不是字大小的倍数，则

type form byte

const (
	zero form = iota
	finite
	inf
)

type RoundingMode byte

const (
)


type Accuracy int8

const (
	Below Accuracy = -1
	Exact Accuracy = 0
	Above Accuracy = +1
)


func (z *Float) SetPrec(prec uint) *Float {

	if prec == 0 {
		z.prec = 0
		if z.form == finite {
			z.acc = makeAcc(z.neg)
			z.form = zero
		}
		return z
	}

	if prec > MaxPrec {
		prec = MaxPrec
	}
	old := z.prec
	z.prec = uint32(prec)
	if z.prec < old {
		z.round(0)
	}
	return z
}

func makeAcc(above bool) Accuracy {
	if above {
		return Above
	}
	return Below
}

func (z *Float) SetMode(mode RoundingMode) *Float {
	z.mode = mode
	z.acc = Exact
	return z
}

func (x *Float) Prec() uint {
	return uint(x.prec)
}

func (x *Float) MinPrec() uint {
	if x.form != finite {
		return 0
	}
	return uint(len(x.mant))*_W - x.mant.trailingZeroBits()
}

func (x *Float) Mode() RoundingMode {
	return x.mode
}

func (x *Float) Acc() Accuracy {
	return x.acc
}

func (x *Float) Sign() int {
	if debugFloat {
		x.validate()
	}
	if x.form == zero {
		return 0
	}
	if x.neg {
		return -1
	}
	return 1
}

func (x *Float) MantExp(mant *Float) (exp int) {
	if debugFloat {
		x.validate()
	}
	if x.form == finite {
		exp = int(x.exp)
	}
	if mant != nil {
		mant.Copy(x)
		if mant.form == finite {
			mant.exp = 0
		}
	}
	return
}

func (z *Float) setExpAndRound(exp int64, sbit uint) {
	if exp < MinExp {
		z.acc = makeAcc(z.neg)
		z.form = zero
		return
	}

	if exp > MaxExp {
		z.acc = makeAcc(!z.neg)
		z.form = inf
		return
	}

	z.form = finite
	z.exp = int32(exp)
	z.round(sbit)
}

func (z *Float) SetMantExp(mant *Float, exp int) *Float {
	if debugFloat {
		z.validate()
		mant.validate()
	}
	z.Copy(mant)

	if z.form == finite {
		z.setExpAndRound(int64(z.exp)+int64(exp), 0)
	}
	return z
}

// 符号位报告x是负还是负零。
func (x *Float) Signbit() bool {
	return x.neg
}

// IsInf报告x是+Inf还是-Inf。
func (x *Float) IsInf() bool {
	return x.form == inf
}

// IsInt报告x是整数。
// /±Inf值不是整数。
func (x *Float) IsInt() bool {
	if debugFloat {
		x.validate()
	}
	// 特殊情况
	if x.form != finite {
		return x.form == zero
	}
	// x.form==有限
	if x.exp <= 0 {
		return false
	}
	// x.exp>0 
	return x.prec <= uint32(x.exp) || x.MinPrec() <= uint(x.exp) // 小数尾数位不足
}

// 调试支持
func (x *Float) validate() {
	if !debugFloat {
		// 避免性能错误
		panic("validate called but debugFloat is not set")
	}
	if x.form != finite {
		return
	}
	m := len(x.mant)
	if m == 0 {
		panic("nonzero finite number with empty mantissa")
	}
	const msb = 1 << (_W - 1)
	if x.mant[m-1]&msb == 0 {
		panic(fmt.Sprintf("msb not set in last word %#x of %s", x.mant[m-1], x.Text('p', 0)))
	}
	if x.prec == 0 {
		panic("zero precision finite number")
	}
}

// 根据z.mode将z四舍五入z.prec位并设置z.acc照着
// sbit必须为0或1，并在调用round之前汇总可能有的任何“粘性位”信息。z的尾数必须规范化（设置msb）
// 或为空。
// 
// 注意：负INF、拓扑位置INF的舍入模式受
// z符号的影响。为了正确的四舍五入，在
// 调用四舍五入之前必须正确设置z的符号。
func (z *Float) round(sbit uint) {
	if debugFloat {
		z.validate()
	}

	z.acc = Exact
	if z.form != finite {
		// /±0或±Inf=>无事可做
		return
	}
	// /z.form==finite&&len（z.mant）>0 
	// /m>0表示z.prec>0（通过验证检查）

	m := uint32(len(z.mant)) // 表示尾数长度的单词
	bits := m * _W           // 表示尾数位；bits>0 
	if bits <= z.prec {
		// 尾数拟合=>无需做
		return
	}
	// bits>z.prec 

	// 舍入基于两个位：舍入位（rbit）和粘性位（sbit）。rbit是紧靠
	// z.prec前导尾数位之前的位（“0.5”）。如果设置rbit前的任何
	// 位（“0.25”、“0.125”等）：
	// 
	// rbit sbit=>“分数部分”
	// 
	// 0==0 

	r := uint(bits - z.prec - 1) // 四舍五入位位置；r>=0 
	rbit := z.mant.bit(r) & 1    // 四舍五入位；请注意安全，并确保它是一个单位
	// 粘性位仅用于对数据进行舍入，即使是
	// 或舍入位为零时。否则避免计算。
	if sbit == 0 && (rbit == 0 || z.mode == ToNearestEven) {
		sbit = z.mant.sticky(r)
	}
	sbit &= 1 // 注意安全，确保它是一个单位

	// 切掉多余的字
	n := (z.prec + (_W - 1)) / _W // 字数尾数长度以达到所需的精度
	if m > n {
		copy(z.mant, z.mant[m-n:]) // 将n个最后一个字移到前面
		z.mant = z.mant[:n]
	}

	// 确定尾数零位（ntz）并计算尾数最低有效字的lsb掩码
	ntz := n*_W - z.prec // 0<=ntz<\u W 
	lsb := Word(1) << ntz

	// 如果结果不精确，则舍入
	if rbit|sbit != 0 {
		// 做出舍入决定：默认情况下，结果尾数被截断（“舍入”）。决定我们是否需要增加（未签名）
		// 尾数或“四舍五入”。
		inc := false
		switch z.mode {
		case ToNegativeInf:
			inc = z.neg
		case ToZero:
			// 无需操作
		case ToNearestEven:
			inc = rbit != 0 && (sbit != 0 || z.mant[0]&lsb != 0)
		case ToNearestAway:
			inc = rbit != 0
		case AwayFromZero:
			inc = true
		case ToPositiveInf:
			inc = !z.neg
		default:
			panic("unreachable")
		}

		// 如果我们递增，则阳性结果（！z.neg）高于精确结果，如果我们截断，则阳性结果（！z.neg）低于精确结果（精确结果不需要四舍五入）。
		// 对于负结果（z.neg），则正好相反。
		z.acc = makeAcc(inc != z.neg)

		if inc {
			// 将1添加到尾数
			if addVW(z.mant, z.mant, lsb) != 0 {
				// 尾数溢出=>调整指数
				if z.exp >= MaxExp {
					// 指数溢出
					z.form = inf
					return
				}
				z.exp++
				// 调整尾数：除以2以补偿指数调整
				shrVU(z.mant, z.mant, 1)
				// 将msb==进位==1从
				const msb = 1 << (_W - 1)
				z.mant[n-1] |= msb
			}
		}
	}

	// 将尾数溢出设置为零在最低有效字
	z.mant[0] &^= lsb - 1

	if debugFloat {
		z.validate()
	}
}

func (z *Float) setBits64(neg bool, x uint64) *Float {
	if z.prec == 0 {
		z.prec = 64
	}
	z.acc = Exact
	z.neg = neg
	if x == 0 {
		z.form = zero
		return z
	}
	// x！=0 
	z.form = finite
	s := bits.LeadingZeros64(x)
	z.mant = z.mant.setUint64(x << uint(s))
	z.exp = int32(64 - s) // 始终适合
	if z.prec < 64 {
		z.round(0)
	}
	return z
}

// SetUint64将z设置为x的（可能四舍五入）值并返回z。
// 如果z的精度为0，则将其更改为64（四舍五入将产生
// 无效）。
func (z *Float) SetUint64(x uint64) *Float {
	return z.setBits64(false, x)
}

// SetInt64将z设置为x的（可能四舍五入）值并返回z。
// 如果z的精度为0，则将其更改为64（四舍五入将产生
// 无效）。
func (z *Float) SetInt64(x int64) *Float {
	u := x
	if u < 0 {
		u = -u
	}
	// 我们不能简单地调用z.SetUint64（uint64（u））然后更改符号，因为符号会影响舍入。
	return z.setBits64(x < 0, uint64(u))
}

// SetFloat64将z设置为x的（可能四舍五入）值并返回z。
// 如果z的精度为0，则将其更改为53（四舍五入将产生
// 无效）。如果x是NaN，SetFloat64将与ErrNaN发生冲突。
func (z *Float) SetFloat64(x float64) *Float {
	if z.prec == 0 {
		z.prec = 53
	}
	if math.IsNaN(x) {
		panic(ErrNaN{"Float.SetFloat64(NaN)"})
	}
	z.acc = Exact
	z.neg = math.Signbit(x) // 句柄-0，-Inf正确
	if x == 0 {
		z.form = zero
		return z
	}
	if math.IsInf(x, 0) {
		z.form = inf
		return z
	}
	// 规范化的x！=0 
	z.form = finite
	fmant, exp := math.Frexp(x) // 获取规范化尾数
	z.mant = z.mant.setUint64(1<<63 | math.Float64bits(fmant)<<11)
	z.exp = int32(exp) // 始终符合
	if z.prec < 53 {
		z.round(0)
	}
	return z
}

// fnorm通过将尾数m移到左侧
// 来规范化尾数m，以使最高有效字（msw）的msb为1。
// 返回移位量。它假设len（m）！=0
func fnorm(m nat) int64 {
	if debugFloat && (len(m) == 0 || m[len(m)-1] == 0) {
		panic("msw of mantissa is 0")
	}
	s := nlz(m[len(m)-1])
	if s > 0 {
		c := shlVU(m, m, s)
		if debugFloat && c != 0 {
			panic("nlz or shlVU incorrect")
		}
	}
	return int64(s)
}

// SetInt将z设置为x的（可能四舍五入）值并返回z。
// 如果z的精度为0，则将其更改为x.BitLen（）
// 或64中的较大值（四舍五入将无效）。
func (z *Float) SetInt(x *Int) *Float {
	// 如果z.prec>0，则TODO（gri）的效率会更高，但与x的大小相比，TODO（gri）会更小，或者如果存在许多尾随的0，则TODO（gri）的效率会更高。
	bits := uint32(x.BitLen())
	if z.prec == 0 {
		z.prec = umax32(bits, 64)
	}
	z.acc = Exact
	z.neg = x.neg
	if len(x.abs) == 0 {
		z.form = zero
		return z
	}
	// x！=0 
	z.mant = z.mant.set(x.abs)
	fnorm(z.mant)
	z.setExpAndRound(int64(bits), 0)
	return z
}

// SetRat将z设置为x的（可能四舍五入）值并返回z。
// 如果z的精度为0，则将其更改为a.BitLen（）、
// b.BitLen（）或64中的最大值；x=a/b时。
func (z *Float) SetRat(x *Rat) *Float {
	if x.IsInt() {
		return z.SetInt(x.Num())
	}
	var a, b Float
	a.SetInt(x.Num())
	b.SetInt(x.Denom())
	if z.prec == 0 {
		z.prec = umax32(a.prec, b.prec)
	}
	return z.Quo(&a, &b)
}

// SetInf如果signbit为
// set，则将z设置为无限浮点-Inf；如果signbit未设置，则将+Inf设置为z，并返回z。z的精度保持不变，结果始终为
// 精确。
func (z *Float) SetInf(signbit bool) *Float {
	z.acc = Exact
	z.form = inf
	z.neg = signbit
	return z
}

// 将z设置为x的（可能四舍五入）值并返回z。
// 如果z的精度为0，则在设置z之前将其更改为x的精度
// 且舍入无效。
// 根据z的精度和舍入方式进行舍入
// 模式；z的精度报告相对于
// 精确（未四舍五入）结果的结果误差。
func (z *Float) Set(x *Float) *Float {
	if debugFloat {
		x.validate()
	}
	z.acc = Exact
	if z != x {
		z.form = x.form
		z.neg = x.neg
		if x.form == finite {
			z.exp = x.exp
			z.mant = z.mant.set(x.mant)
		}
		if z.prec == 0 {
			z.prec = x.prec
		} else if z.prec < x.prec {
			z.round(0)
		}
	}
	return z
}

// 复制将z设置为x，精度、舍入模式和
// 精度与x相同，并返回z。即使z和
// x相同，x也不会改变。
func (z *Float) Copy(x *Float) *Float {
	if debugFloat {
		x.validate()
	}
	if z != x {
		z.prec = x.prec
		z.mode = x.mode
		z.acc = x.acc
		z.form = x.form
		z.neg = x.neg
		if z.form == finite {
			z.mant = z.mant.set(x.mant)
			z.exp = x.exp
		}
	}
	return z
}

// msb32返回x的32个最高有效位。
func msb32(x nat) uint32 {
	i := len(x) - 1
	if i < 0 {
		return 0
	}
	if debugFloat && x[i]&(1<<(_W-1)) == 0 {
		panic("x not normalized")
	}
	switch _W {
	case 32:
		return uint32(x[i])
	case 64:
		return uint32(x[i] >> 32)
	}
	panic("unreachable")
}

// msb64返回x的64个最高有效位。
func msb64(x nat) uint64 {
	i := len(x) - 1
	if i < 0 {
		return 0
	}
	if debugFloat && x[i]&(1<<(_W-1)) == 0 {
		panic("x not normalized")
	}
	switch _W {
	case 32:
		v := uint64(x[i]) << 32
		if i > 0 {
			v |= uint64(x[i-1])
		}
		return v
	case 64:
		return uint64(x[i])
	}
	panic("unreachable")
}

// Uint64返回因将x向零截断而产生的无符号整数
// 。如果0<=x<=math.MaxUint64，则结果为精确的
// 如果x为整数，否则为整数以下。
// 对于x<0，结果是（0，上面），对于x>math.maxint64，结果是（math.maxint64，下面）
// 对于x>math.maxint64。
func (x *Float) Uint64() (uint64, Accuracy) {
	if debugFloat {
		x.validate()
	}

	switch x.form {
	case finite:
		if x.neg {
			return 0, Above
		}
		// 0<x<+Inf 
		if x.exp <= 0 {
			// 0<x<1 
			return 0, Below
		}
		// 1<=x<Inf 
		if x.exp <= 64 {
			// u=trunc（x）适合于uint64 
			u := msb64(x.mant) >> (64 - uint32(x.exp))
			if x.MinPrec() <= 64 {
				return u, Exact
			}
			return u, Below // x截断
		}
		// x过大
		return math.MaxUint64, Below

	case zero:
		return 0, Exact

	case inf:
		if x.neg {
			return 0, Above
		}
		return math.MaxUint64, Below
	}

	panic("unreachable")
}

// Int64返回因将x截断为零而产生的整数。
// 如果math.MinInt64<=x<=math.MaxInt64，则如果x是一个整数，则结果是精确的，否则大于（x<0）或小于（x>0）。
// 对于x<math.MinInt64，
// 和（math.MaxInt64，下面）对于x>math.MaxInt64，结果是（math.MinInt64，上面）。
func (x *Float) Int64() (int64, Accuracy) {
	if debugFloat {
		x.validate()
	}

	switch x.form {
	case finite:
		// 0<|x |<+Inf 
		acc := makeAcc(x.neg)
		if x.exp <= 0 {
			// 0<|x |<1 
			return 0, acc
		}
		// x.exp>0 

		// 1<=| x |<Inf 
		if x.exp <= 63 {
			// i=trunc（x）适合于int64（不包括数学MinInt64）
			i := int64(msb64(x.mant) >> (64 - uint32(x.exp)))
			if x.neg {
				i = -i
			}
			if x.MinPrec() <= uint(x.exp) {
				return i, Exact
			}
		}
		if x.neg {
			if x.exp == 64 && x.MinPrec() == 1 {
				acc = Exact
			}
			return math.MinInt64, acc
		}
		// x太大
		return math.MaxInt64, Below

	case zero:
		return 0, Exact

	case inf:
		if x.neg {
			return math.MinInt64, Above
		}
		return math.MaxInt64, Below
	}

	panic("unreachable")
}

// Float32返回最接近x的Float32值。如果x太小而不能用float32（|x |<math.SmallestNonzeroFloat32）表示，则结果
// 分别为（0，低于）或（-0，高于），具体取决于x的符号。
// 如果x太大，无法用float32（|x |>math.MaxFloat32）表示，则结果为（+Inf，上面）或（-Inf，下面），具体取决于x的符号。
func (x *Float) Float32() (float32, Accuracy) {
	if debugFloat {
		x.validate()
	}

	switch x.form {
	case finite:
		// 0<|x |<+Inf 

		const (
			fbits = 32                // 浮点大小
			mbits = 23                // 尾数大小（不含隐式msb）
			ebits = fbits - mbits - 1 // 8指数大小
			bias  = 1<<(ebits-1) - 1  // 127指数偏差
			dmin  = 1 - bias - mbits  // /-149最小无偏指数（非正规）
			emin  = 1 - bias          // -126最小无偏指数（正态）
			emax  = bias              // 127最大无偏指数（正态）
		)

		// /浮点尾数m为0.5<=m<1.0；计算32尾数的指数e。
		e := x.exp - 1 // 1.0<=m<2.0的正常尾数m的指数

		// 计算浮点32尾数的精度p。
		// 如果指数太小，则在
		// 四舍五入之前有一个非规范数，可用精度小于p尾数位
		// （指数保持不变，但尾数右移）。
		p := mbits + 1 // 普通浮点的精度
		if e < emin {
			// 重新计算精度
			p = mbits + 1 - emin + int(e)
			// 如果p==0，x的尾数会向右移动很多
			// 以至于其msb立即落在浮点32 
			// 尾数空间的右侧。换句话说，如果最小的非规范值是
			// 被认为是“1.0”，对于p==0，尾数值m>=0.5。
			// 如果m>0.5，则四舍五入为1.0；i、 e.最小的非规范值。
			// 如果m==0.5，则向下舍入为偶数，即0.0。
			if p < 0 /* m <= 0.25 */ || p == 0 && x.mant.sticky(uint(len(x.mant))*_W-1) == 0 /* m == 0.5 */ {
				if x.neg {
					var z float32
					return -z, Above
				}
				return 0.0, Below
			}
			if p == 0 {
				if x.neg {
					return -math.SmallestNonzeroFloat32, Below
				}
				return math.SmallestNonzeroFloat32, Above
			}
		}

		var r Float
		r.prec = uint32(p)
		r.Set(x)
		e = r.exp - 1

		if r.form == inf || e > emax {
			if x.neg {
				return float32(math.Inf(-1)), Below
			}
			return float32(math.Inf(+1)), Above
		}

		var sign, bexp, mant uint32
		if x.neg {
			sign = 1 << (fbits - 1)
		}

		if e < emin {
			p = mbits + 1 - emin + int(e)
			mant = msb32(r.mant) >> uint(fbits-p)
		} else {
			bexp = uint32(e+bias) << mbits
		}

		return math.Float32frombits(sign | bexp | mant), r.acc

	case zero:
		if x.neg {
			var z float32
			return -z, Exact
		}
		return 0.0, Exact

	case inf:
		if x.neg {
			return float32(math.Inf(-1)), Exact
		}
		return float32(math.Inf(+1)), Exact
	}

	panic("unreachable")
}

func (x *Float) Float64() (float64, Accuracy) {
	if debugFloat {
		x.validate()
	}

	switch x.form {
	case finite:

		const (
		)


		if e < emin {
			p = mbits + 1 - emin + int(e)
			if p < 0 /* m <= 0.25 */ || p == 0 && x.mant.sticky(uint(len(x.mant))*_W-1) == 0 /* m == 0.5 */ {
				if x.neg {
					var z float64
					return -z, Above
				}
				return 0.0, Below
			}
			if p == 0 {
				if x.neg {
					return -math.SmallestNonzeroFloat64, Below
				}
				return math.SmallestNonzeroFloat64, Above
			}
		}

		var r Float
		r.prec = uint32(p)
		r.Set(x)
		e = r.exp - 1

		if r.form == inf || e > emax {
			if x.neg {
				return math.Inf(-1), Below
			}
			return math.Inf(+1), Above
		}

		var sign, bexp, mant uint64
		if x.neg {
			sign = 1 << (fbits - 1)
		}

		if e < emin {
			p = mbits + 1 - emin + int(e)
			mant = msb64(r.mant) >> uint(fbits-p)
		} else {
			bexp = uint64(e+bias) << mbits
		}

		return math.Float64frombits(sign | bexp | mant), r.acc

	case zero:
		if x.neg {
			var z float64
			return -z, Exact
		}
		return 0.0, Exact

	case inf:
		if x.neg {
			return math.Inf(-1), Exact
		}
		return math.Inf(+1), Exact
	}

	panic("unreachable")
}

func (x *Float) Int(z *Int) (*Int, Accuracy) {
	if debugFloat {
		x.validate()
	}

	if z == nil && x.form <= finite {
		z = new(Int)
	}

	switch x.form {
	case finite:
		acc := makeAcc(x.neg)
		if x.exp <= 0 {
			return z.SetInt64(0), acc
		}

		allBits := uint(len(x.mant)) * _W
		exp := uint(x.exp)
		if x.MinPrec() <= exp {
			acc = Exact
		}
		// 根据需要移位尾数
		if z == nil {
			z = new(Int)
		}
		z.neg = x.neg
		switch {
		case exp > allBits:
			z.abs = z.abs.shl(x.mant, exp-allBits)
		default:
			z.abs = z.abs.set(x.mant)
		case exp < allBits:
			z.abs = z.abs.shr(x.mant, allBits-exp)
		}
		return z, acc

	case zero:
		return z.SetInt64(0), Exact

	case inf:
		return nil, makeAcc(x.neg)
	}

	panic("unreachable")
}

// Rat返回x对应的有理数；
// 如果x是无穷大，则为零。
// 如果x不是Inf，则结果准确。
// 如果提供了非nil*Rat参数z，Rat将
// 结果存储在z中，而不是分配新Rat。
func (x *Float) Rat(z *Rat) (*Rat, Accuracy) {
	if debugFloat {
		x.validate()
	}

	if z == nil && x.form <= finite {
		z = new(Rat)
	}

	switch x.form {
	case finite:
		// 0<|x |<+Inf 
		allBits := int32(len(x.mant)) * _W
		// /建立分子和分母
		z.a.neg = x.neg
		switch {
		case x.exp > allBits:
			z.a.abs = z.a.abs.shl(x.mant, uint(x.exp-allBits))
			z.b.abs = z.b.abs[:0] // ==1（见鼠）
			// /z已为正常形式
		default:
			z.a.abs = z.a.abs.set(x.mant)
			z.b.abs = z.b.abs[:0] // =1（见鼠）
			// /z已为正常形式
		case x.exp < allBits:
			z.a.abs = z.a.abs.set(x.mant)
			t := z.b.abs.setUint64(1)
			z.b.abs = t.shl(t, uint(allBits-x.exp))
			z.norm()
		}
		return z, Exact

	case zero:
		return z.SetInt64(0), Exact

	case inf:
		return nil, makeAcc(x.neg)
	}

	panic("unreachable")
}

// /Abs将z设置为（可能四舍五入的）值（x的绝对值）
// 并返回z。
func (z *Float) Abs(x *Float) *Float {
	z.Set(x)
	z.neg = false
	return z
}

// 负将z设置为（可能四舍五入）符号为负数的x的值，返回z.
func (z *Float) Neg(x *Float) *Float {
	z.Set(x)
	z.neg = !z.neg
	return z
}

func validateBinaryOperands(x, y *Float) {
	if !debugFloat {
		// 避免性能错误
		panic("validateBinaryOperands called but debugFloat is not set")
	}
	if len(x.mant) == 0 {
		panic("empty mantissa for x")
	}
	if len(y.mant) == 0 {
		panic("empty mantissa for y")
	}
}

// z=x+y，对加法忽略x和y的符号
// 但使用z的符号四舍五入结果。
// x和y必须具有非空尾数和有效指数。
func (z *Float) uadd(x, y *Float) {
	// 注意：此实现需要2个移位，大部分
	// 时间。如果
	// 的指数或精度相差很大，则效率也很低。下面的文章介绍了
	// 一种高效（但更复杂）的方法实现
	// 与此处使用的内部表示兼容：
	// 
	// Vincent Lefèvre:“通用多精度浮点-
	// 带精确舍入的点加法（如MPFR库中所示）”
	// http:

	if debugFloat {
		validateBinaryOperands(x, y)
	}

	// 计算带有“二进制点”
	// 右侧尾数的指数ex，ey（尾数.0）-使用int64避免溢出
	ex := int64(x.exp) - int64(len(x.mant))*_W
	ey := int64(y.exp) - int64(len(y.mant))*_W

	al := alias(z.mant, x.mant) || alias(z.mant, y.mant)

	// TODO（gri）拥有一个组合的add和shift原语
	// 可以使此代码大大加快
	switch {
	case ex < ey:
		if al {
			t := nat(nil).shl(y.mant, uint(ey-ex))
			z.mant = z.mant.add(x.mant, t)
		} else {
			z.mant = z.mant.shl(y.mant, uint(ey-ex))
			z.mant = z.mant.add(x.mant, z.mant)
		}
	default:
		// ex==ey，不需要移位
		z.mant = z.mant.add(x.mant, y.mant)
	case ex > ey:
		if al {
			t := nat(nil).shl(x.mant, uint(ex-ey))
			z.mant = z.mant.add(t, y.mant)
		} else {
			z.mant = z.mant.shl(x.mant, uint(ex-ey))
			z.mant = z.mant.add(z.mant, y.mant)
		}
		ex = ey
	}
	// len（z.mant）>0 

	z.setExpAndRound(ex+int64(len(z.mant))*_W-fnorm(z.mant), 0)
}

// z=x-y表示| x |>| y |，忽略x和y的符号表示减法
// 但使用z的符号来舍入结果。
// x和y必须具有非空尾数和有效指数。
func (z *Float) usub(x, y *Float) {
	// 此代码与uadd对称。
	// 我们没有考虑通用代码输出，因为uadd（和usub）最终应该通过特殊的外壳进行优化，代码会发散。

	if debugFloat {
		validateBinaryOperands(x, y)
	}

	ex := int64(x.exp) - int64(len(x.mant))*_W
	ey := int64(y.exp) - int64(len(y.mant))*_W

	al := alias(z.mant, x.mant) || alias(z.mant, y.mant)

	switch {
	case ex < ey:
		if al {
			t := nat(nil).shl(y.mant, uint(ey-ex))
			z.mant = t.sub(x.mant, t)
		} else {
			z.mant = z.mant.shl(y.mant, uint(ey-ex))
			z.mant = z.mant.sub(x.mant, z.mant)
		}
	default:
		// ex==ey，不需要移位
		z.mant = z.mant.sub(x.mant, y.mant)
	case ex > ey:
		if al {
			t := nat(nil).shl(x.mant, uint(ex-ey))
			z.mant = t.sub(t, y.mant)
		} else {
			z.mant = z.mant.shl(x.mant, uint(ex-ey))
			z.mant = z.mant.sub(z.mant, y.mant)
		}
		ex = ey
	}

	// 操作数可能已经相互抵消了
	if len(z.mant) == 0 {
		z.acc = Exact
		z.form = zero
		z.neg = false
		return
	}
	// len（z.mant）>0 

	z.setExpAndRound(ex+int64(len(z.mant))*_W-fnorm(z.mant), 0)
}

// z=x*y，对于乘法
// 忽略x和y的符号，但使用z的符号对结果进行舍入。
// x和y必须具有非空尾数和有效指数。
func (z *Float) umul(x, y *Float) {
	if debugFloat {
		validateBinaryOperands(x, y)
	}

	// 注意：如果z的精度小于n x 
	// 和y的精度之和，通常情况下（例如，如果所有浮点
	// 具有相同的精度）。
	// TODO（gri）针对常见情况对此进行优化。

	e := int64(x.exp) + int64(y.exp)
	if x == y {
		z.mant = z.mant.sqr(x.mant)
	} else {
		z.mant = z.mant.mul(x.mant, y.mant)
	}
	z.setExpAndRound(e-fnorm(z.mant), 0)
}

// z=x/y，在除法中忽略x和y的符号
// 但使用z的符号对结果进行四舍五入。
// x和y必须具有非空尾数和有效指数。
func (z *Float) uquo(x, y *Float) {
	if debugFloat {
		validateBinaryOperands(x, y)
	}

	// words尾数长度以获得所需的结果精度+1 
	// （至少有一个额外的位，因此我们在除法后得到四舍五入位）
	n := int(z.prec/_W) + 1

	// compute adjusted x.mant，以便我们得到足够的结果精度
	xadj := x.mant
	if d := n - len(x.mant) + len(y.mant); d > 0 {
		// d额外需要的字=>将d“0位”添加到x 
		xadj = make(nat, len(x.mant)+d)
		copy(xadj[d:], x.mant)
	}
	// TODO（gri）：如果我们有太多的数字（d<0），我们应该能够缩短x以加快除法速度。但在这种情况下，我们必须格外小心使用四舍五入。除法前计算d，因为x.mant可能有别名。通过xadj）或者y.mant和z.mant.

	d := len(xadj) - len(y.mant)

	// 除以
	var r nat
	z.mant, r = z.mant.div(nil, xadj, y.mant)
	e := int64(x.exp) - int64(y.exp) - int64(d-len(z.mant))*_W

	// 结果足够长，可以包含（至少）舍入位。如果有非零余数，则相应的小数部分
	// （如果计算）将有非零粘性位（如果它是
	// zero，则不能有非零余数）.
	var sbit uint
	if len(r) > 0 {
		sbit = 1
	}

	z.setExpAndRound(e-fnorm(z.mant), sbit)
}

// ucmp返回-1、0或+1，具体取决于
// 
func (x *Float) ucmp(y *Float) int {
	if debugFloat {
		validateBinaryOperands(x, y)
	}

	switch {
	case x.exp < y.exp:
		return -1
	case x.exp > y.exp:
		return +1
	}

	i := len(x.mant)
	j := len(y.mant)
	for i > 0 || j > 0 {
		var xm, ym Word
		if i > 0 {
			i--
			xm = x.mant[i]
		}
		if j > 0 {
			j--
			ym = y.mant[j]
		}
		switch {
		case xm < ym:
			return -1
		case xm > ym:
			return +1
		}
	}

	return 0
}


func (z *Float) Add(x, y *Float) *Float {
	if debugFloat {
		x.validate()
		y.validate()
	}

	if z.prec == 0 {
		z.prec = umax32(x.prec, y.prec)
	}

	if x.form == finite && y.form == finite {

		yneg := y.neg

		z.neg = x.neg
		if x.neg == yneg {
			z.uadd(x, y)
		} else {
			if x.ucmp(y) > 0 {
				z.usub(x, y)
			} else {
				z.neg = !z.neg
				z.usub(y, x)
			}
		}
		if z.form == zero && z.mode == ToNegativeInf && z.acc == Exact {
			z.neg = true
		}
		return z
	}

	if x.form == inf && y.form == inf && x.neg != y.neg {
		z.acc = Exact
		z.form = zero
		z.neg = false
		panic(ErrNaN{"addition of infinities with opposite signs"})
	}

	if x.form == zero && y.form == zero {
		z.acc = Exact
		z.form = zero
		return z
	}

	if x.form == inf || y.form == zero {
		return z.Set(x)
	}

	return z.Set(y)
}

func (z *Float) Sub(x, y *Float) *Float {
	if debugFloat {
		x.validate()
		y.validate()
	}

	if z.prec == 0 {
		z.prec = umax32(x.prec, y.prec)
	}

	if x.form == finite && y.form == finite {
		yneg := y.neg
		z.neg = x.neg
		if x.neg != yneg {
			z.uadd(x, y)
		} else {
			if x.ucmp(y) > 0 {
				z.usub(x, y)
			} else {
				z.neg = !z.neg
				z.usub(y, x)
			}
		}
		if z.form == zero && z.mode == ToNegativeInf && z.acc == Exact {
			z.neg = true
		}
		return z
	}

	if x.form == inf && y.form == inf && x.neg == y.neg {
		z.acc = Exact
		z.form = zero
		z.neg = false
		panic(ErrNaN{"subtraction of infinities with equal signs"})
	}

	if x.form == zero && y.form == zero {
		z.acc = Exact
		z.form = zero
		return z
	}

	if x.form == inf || y.form == zero {
		return z.Set(x)
	}

	return z.Neg(y)
}

func (z *Float) Mul(x, y *Float) *Float {
	if debugFloat {
		x.validate()
		y.validate()
	}

	if z.prec == 0 {
		z.prec = umax32(x.prec, y.prec)
	}

	z.neg = x.neg != y.neg

	if x.form == finite && y.form == finite {
		z.umul(x, y)
		return z
	}

	z.acc = Exact
	if x.form == zero && y.form == inf || x.form == inf && y.form == zero {
		z.form = zero
		z.neg = false
		panic(ErrNaN{"multiplication of zero with infinity"})
	}

	if x.form == inf || y.form == inf {
		z.form = inf
		return z
	}

	z.form = zero
	return z
}

func (z *Float) Quo(x, y *Float) *Float {
	if debugFloat {
		x.validate()
		y.validate()
	}

	if z.prec == 0 {
		z.prec = umax32(x.prec, y.prec)
	}

	z.neg = x.neg != y.neg

	if x.form == finite && y.form == finite {
		z.uquo(x, y)
		return z
	}

	z.acc = Exact
	if x.form == zero && y.form == zero || x.form == inf && y.form == inf {
		z.form = zero
		z.neg = false
		panic(ErrNaN{"division of zero by zero or infinity by infinity"})
	}

	if x.form == zero || y.form == inf {
		z.form = zero
		return z
	}

	z.form = inf
	return z
}

func (x *Float) Cmp(y *Float) int {
	if debugFloat {
		x.validate()
		y.validate()
	}

	mx := x.ord()
	my := y.ord()
	switch {
	case mx < my:
		return -1
	case mx > my:
		return +1
	}

	switch mx {
	case -1:
		return y.ucmp(x)
	case +1:
		return x.ucmp(y)
	}

	return 0
}

func (x *Float) ord() int {
	var m int
	switch x.form {
	case finite:
		m = 1
	case zero:
		return 0
	case inf:
		m = 2
	}
	if x.neg {
		m = -m
	}
	return m
}

func umax32(x, y uint32) uint32 {
	if x > y {
		return x
	}
	return y
}
